#include <stdio.h>
#include <string.h>
#include <SLES/OpenSLES.h>
#include <android/log.h>
#include <assert.h>
#include "com_lide_rtmpplayer_Player.h"

enum _bool {
	false = 0,
	true
};
typedef enum _bool bool;
/* engine interface */
static SLObjectItf engineObject = NULL;
static SLEngineItf engineEngine;
/* output mix interfaces */
static SLObjectItf outputMixObject = NULL;
static SLEnvironmentalReverbItf outputMixEnvironmentalReverb = NULL;
/* aux effect on the output mix */
static const SLEnvironmentalReverbSettings reverbSettings =
SL_I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR;
/* uri player interfaces */
static SLObjectItf uriPlayerObject = NULL;
static SLPlayItf uriPlayerPlay;
static SLSeekItf uriPlayerSeek;

void createEngine()
{
	SLresult result;
	// create engine
	result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
	assert(SL_RESULT_SUCCESS == result);
	// realize the engine
	result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
	assert(SL_RESULT_SUCCESS == result);
	// get the engine interface
	result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
	assert(SL_RESULT_SUCCESS === result);
	// create output mix
	const SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB};
	const SLboolean req[1] = {SL_BOOLEAN_FALSE};
	result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, ids, req);
	assert(SL_RESULT_SUCCESS == result);
	// realize the output mix
	result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
	assert(SL_RESULT_SUCCESS == result);
	// ignore unsuccessful result codes for env reverb
}

bool createUriAudioPlayer(const char* uri)
{
	SLresult result;
	// config audio source
	SLDataLocator_URI loc_uri = {SL_DATALOCATOR_URI, (SLchar *) uri};
	SLDataFormat_MIME format_mime = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED};
	SLDataSource audioSrc = {&loc_uri, &format_mime};
	// config audio sink
	SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
	SLDataSink audioSnk = {&loc_outmix, NULL};
	// create audio player
	const SLInterfaceID ids[1] = {SL_IID_SEEK};
	const SLboolean req[1] = {SL_BOOLEAN_TRUE};
	result = (*engineEngine)->CreateAudioPlayer(engineEngine, &uriPlayerObject, &audioSrc, &audioSnk, 1, ids, req);
	assert(SL_RESULT_SUCCESS == result);
	// realize the player
	result = (*uriPlayerObject)->Realize(uriPlayerObject, SL_BOOLEAN_FALSE);
	if(SL_RESULT_SUCCESS != result) {
		(*uriPlayerObject)->Destroy(uriPlayerObject);
		uriPlayerObject = NULL;
		return false;
	}
	// get the play interface
	result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_PLAY, &uriPlayerPlay);
	assert(SL_RESULT_SUCCESS == result);
	// get the seek interface
	result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_SEEK, &uriPlayerSeek);
	assert(SL_RESULT_SUCCESS == result);
	// enable whole file looping
	result = (*uriPlayerSeek)->SetLoop(uriPlayerSeek, SL_BOOLEAN_TRUE, 0, SL_TIME_UNKNOWN);
	assert(SL_RESULT_SUCCESS == result);
	return true;
}

void setPlayingUriAudioPlayer(bool played)
{
	SLresult result;
	if (uriPlayerPlay != NULL) {
		result = (*uriPlayerPlay)->SetPlayState(uriPlayerPlay, played ?
				SL_PLAYSTATE_PLAYING : SL_PLAYSTATE_PAUSED);
		assert(SL_RESULT_SUCCESS == result);
	}
}

void destroyUriAudioPlayer()
{
	SLresult result;
}

/*
 * Class:     com_lide_rtmpplayer_Player
 * Method:    Init
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_lide_rtmpplayer_Player_Init
(JNIEnv *evn, jobject obj)
{
	createEngine();
}

/*
 * Class:     com_lide_rtmpplayer_Player
 * Method:    Open
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_com_lide_rtmpplayer_Player_Open
(JNIEnv *evn, jobject obj, jstring RtmpUrl)
{
	const char* file_url = (*evn)->GetStringUTFChars(evn, RtmpUrl, 0);
	createUriAudioPlayer(file_url);
}

/*
 * Class:     com_lide_rtmpplayer_Player
 * Method:    Play
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_lide_rtmpplayer_Player_Play
  (JNIEnv *evn, jobject obj)
{
	setPlayingUriAudioPlayer(true);
}

/*
 * Class:     com_lide_rtmpplayer_Player
 * Method:    Pause
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_lide_rtmpplayer_Player_Pause
  (JNIEnv *evn, jobject obj)
{
	setPlayingUriAudioPlayer(false);
}

/*
 * Class:     com_lide_rtmpplayer_Player
 * Method:    Close
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_lide_rtmpplayer_Player_Close
(JNIEnv *evn, jobject obj)
{

}

/*
 * Class:     com_lide_rtmpplayer_Player
 * Method:    Deinit
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_lide_rtmpplayer_Player_Deinit
(JNIEnv *evn, jobject obj)
{

}
